package com.cuon.ch09.programobject;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;


import com.cuon.Utils;
import com.cuon.ch09.programobject.Data3DList.Data3D;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;

public class ProgramObject extends Activity implements GLSurfaceView.Renderer {
  // 単色描画用の頂点シェーダのプログラム
  private static final String SOLID_VSHADER_SOURCE =
    "attribute vec4 a_Position;\n" +
    "attribute vec4 a_Normal;\n" +
    "uniform mat4 u_MvpMatrix;\n" +
    "uniform mat4 u_NormalMatrix;\n" +
    "varying vec4 v_Color;\n" +
    "void main() {\n" +
    "  vec3 lightDirection = vec3(0.0, 0.0, 1.0);\n" + // 光の向き(ワールド座標)
    "  vec4 color = vec4(0.0, 1.0, 1.0, 1.0);\n" +     // 面の色
    "  gl_Position = u_MvpMatrix * a_Position;\n" +
    "  vec3 normal = normalize(vec3(u_NormalMatrix * a_Normal));\n" +
    "  float nDotL = max(dot(normal, lightDirection), 0.0);\n" +
    "  v_Color = vec4(color.rgb * nDotL, color.a);\n" +
    "}\n";

  // 単色描画用のフラグメントシェーダのプログラム
  private static final String SOLID_FSHADER_SOURCE =
    "#ifdef GL_ES\n" +
    "precision mediump float;\n" +
    "#endif\n" +
    "varying vec4 v_Color;\n" +
    "void main() {\n" +
    "  gl_FragColor = v_Color;\n" +
    "}\n";

  // テクスチャ描画用の頂点シェーダのプログラム
  private static final String TEXTURE_VSHADER_SOURCE =
    "attribute vec4 a_Position;\n" +
    "attribute vec4 a_Normal;\n" +
	"attribute vec4 a_Color;\n" +
    "attribute vec2 a_TexCoord;\n" +
    "uniform mat4 u_MvpMatrix;\n" +
    "uniform mat4 u_NormalMatrix;\n" +
    "varying float v_NdotL;\n" +
    "varying vec2 v_TexCoord;\n" +
    "varying vec4 v_Color;\n" +
    "void main() {\n" +
    "  vec3 lightDirection = vec3(0.0, 0.0, 1.0);\n" + // 光の向き(ワールド座標)
    "  gl_Position = u_MvpMatrix * a_Position;\n" +
    "  vec3 normal = normalize(vec3(u_NormalMatrix * a_Normal));\n" +
    "  v_NdotL = max(dot(normal, lightDirection), 0.0);\n" +
    "  v_TexCoord = a_TexCoord;\n" +
    "  v_Color = a_Color;\n" +
    "}\n";

  // テクスチャ描画用のフラグメントシェーダのプログラム
  private static final String TEXTURE_FSHADER_SOURCE =
    "#ifdef GL_ES\n" +
    "precision mediump float;\n" +
    "#endif\n" +
    "uniform sampler2D u_Sampler;\n" +
    "varying vec2 v_TexCoord;\n" +
    "varying float v_NdotL;\n" +
    "varying vec4 v_Color;\n" +
    "void main() {\n" +
    "  vec4 color = texture2D(u_Sampler, v_TexCoord);\n" +
    //"  gl_FragColor = vec4(color.rgb * v_NdotL, color.a);\n" +
    "  gl_FragColor = v_Color;\n" +
    "}\n";

  // メンバー変数
  //private Shader mSolidShader; // 単色の立方体を描画するシェーダ
  private Shader mTexShader;   // テクスチャ付きの立方体を描画するシェーダ

  private Model mCube;     // 描画する立方体

//  private Model mGraph;

  private int mTexture;    // テクスチャオブジェクト

  // 座標変換行列
  private float[] mModelMatrix = new float[16];    // モデル行列
  private float[] mViewProjMatrix = new float[16]; // ビュー投影行列
  private float[] mMvpMatrix = new float[16];   // モデルビュー投影行列
  private float[] mNormalMatrix = new float[16];// 法線の座標変換用行列


//  private float mCurrentAngle;  // 立方体の現在の回転角
//  private long mLast; // 最後に呼び出された時刻


  private float[] mCurrentAngle = {0.0f, 0.0f}; // 現在の回転角([x軸, y軸]度)
  private float mLastX = -1.0f, mLastY = -1.0f; // 最後にタッチされた位置
  private float mSize;      // 画面の縦のサイズ

  private long mLast; // 最後に呼び出された時刻
  private float mScale = 1.0f; // 現在の拡大縮小率
  // ピンチインアウトを検出するためのクラス
  private ScaleGestureDetector mScaleGestureDetector;

  GLSurfaceView glSurfaceView;



  public class Shader {     // シェーダと関連する変数を管理するクラス
	public int program = -1;     // プログラムオブジェクト
    public int a_Position = -1;  // attribute変数の格納場所
    public int a_Normal = -1;
    public int a_TexCoord = -1;
    public int u_MvpMatrix = -1; // uniform変数の格納場所
    public int u_NormalMatrix = -1;
    public int u_Sampler = -1;
    public int a_Color=-1;
  }

  public class Model { // モデルを構成するバッファオブジェクトを管理するクラス
	public BufferObject vertexBuffer;    // 頂点座標用のバッファオブジェクト
	public BufferObject texCoordBuffer;  // テクスチャ座標用のバッファオブジェクト
	public BufferObject normalBuffer;    // 法線用のバッファオブジェクト
	public BufferObject colorBuffer;    // 法線用のバッファオブジェクト
	public BufferObject indexBuffer;     // インデックス用のバッファオブジェクト
	public int numIndices;
  }

  public class BufferObject { // バッファと関連する変数を管理するクラス
    public int buffer; // バッファオブジェクト
    public int num;    // 成分数
    public int type;   // データ型
  }




  @Override
  public boolean onTouchEvent(MotionEvent event) {
    mScaleGestureDetector.onTouchEvent(event); // ピンチインアウトの処理を依頼する

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN: {
        float x = event.getX(), y = event.getY();
        mLastX = x; mLastY = y; // 現在の位置を保存しておく
      }
      break;


    case MotionEvent.ACTION_MOVE: {

        float x = event.getX(), y = event.getY();
        float factor = 100.0f / mSize; // 指の移動に対する回転の倍率
        float dx = factor * (x - mLastX);
        float dy = factor * (y - mLastY);

        // x軸周りの回転角は-360度～360度に制限する
        mCurrentAngle[0] = Math.max(Math.min(mCurrentAngle[0] + dy, 360.0f), -360.0f);

        //mCurrentAngle[1] = mCurrentAngle[1] + dx;
        mCurrentAngle[1] = Math.max(Math.min(mCurrentAngle[1] + dx, 360.0f), -360.0f);

        mLastX = x; mLastY = y; // 現在の位置を保存しておく
        glSurfaceView.requestRender(); // 描画を依頼する

      }
      break;
    }

    return super.onTouchEvent(event);
  }




  /** Called when the activity is first created. */
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // OpenGL ES 2.0が使用できるように初期化する
    glSurfaceView = Utils.initGLES20(this, this);
    setContentView(glSurfaceView);// GLSurfaceViewをこのアプリケーションの画面として使用する

    // ピンチインアウトの検出用のクラスを使用する
    mScaleGestureDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.SimpleOnScaleGestureListener() {
      private float mPrevScale; // 前の拡大縮小率

      @Override
      public boolean onScaleBegin(ScaleGestureDetector detector) { // 2本指で画面に触れた
        mPrevScale = mScale; // 前の拡大縮小率を保存
        return super.onScaleBegin(detector);
      }

      @Override
      public boolean onScale(ScaleGestureDetector detector) { // 指が動いた
        mScale = detector.getScaleFactor() * mPrevScale;  // ピンチインアウトによる拡大縮小率の修正
        return super.onScale(detector);
      }

      @Override
      public void onScaleEnd(ScaleGestureDetector detector) { // 画面から指が離れた
        mScale = detector.getScaleFactor() * mPrevScale;  // ピンチインアウトによる拡大縮小率の修正
        super.onScaleEnd(detector);
      }
    });
  }

  public void onSurfaceCreated(GL10 gl, EGLConfig config) {
	// シェーダを初期化する
	int solidProgram = Utils.createProgram(SOLID_VSHADER_SOURCE, SOLID_FSHADER_SOURCE);
	int texProgram = Utils.createProgram(TEXTURE_VSHADER_SOURCE, TEXTURE_FSHADER_SOURCE);

    // 単色描画用のシェーダのattribute、uniform変数の格納場所を取得
//    mSolidShader = new Shader();
//    mSolidShader.program = solidProgram;
//    mSolidShader.a_Position = GLES20.glGetAttribLocation(mSolidShader.program, "a_Position");
//    mSolidShader.a_Normal = GLES20.glGetAttribLocation(mSolidShader.program, "a_Normal");
//    mSolidShader.u_MvpMatrix = GLES20.glGetUniformLocation(mSolidShader.program, "u_MvpMatrix");
//    mSolidShader.u_NormalMatrix = GLES20.glGetUniformLocation(mSolidShader.program, "u_NormalMatrix");

    // テクスチャ描画用のシェーダのattribute、uniform変数の格納場所を取得
    mTexShader = new Shader();
    mTexShader.program = texProgram;
    mTexShader.a_Position = GLES20.glGetAttribLocation(mTexShader.program, "a_Position");
    mTexShader.a_Color = GLES20.glGetAttribLocation(mTexShader.program, "a_Color");
    mTexShader.a_Normal = GLES20.glGetAttribLocation(mTexShader.program, "a_Normal");
    mTexShader.a_TexCoord = GLES20.glGetAttribLocation(mTexShader.program, "a_TexCoord");
    mTexShader.u_MvpMatrix = GLES20.glGetUniformLocation(mTexShader.program, "u_MvpMatrix");
    mTexShader.u_NormalMatrix = GLES20.glGetUniformLocation(mTexShader.program, "u_NormalMatrix");
    mTexShader.u_Sampler = GLES20.glGetUniformLocation(mTexShader.program, "u_Sampler");

//    if (mSolidShader.a_Position == -1 || mSolidShader.a_Normal == -1 ||
//      mSolidShader.u_MvpMatrix == -1 || mSolidShader.u_NormalMatrix == -1 ||
//      mTexShader.a_Position == -1 || mTexShader.a_Normal == -1 || mTexShader.a_TexCoord == -1 ||
//      mTexShader.u_MvpMatrix == -1 || mTexShader.u_NormalMatrix == -1 || mTexShader.u_Sampler == -1) {
//      throw new RuntimeException("attribute、uniform変数の格納場所の取得に失敗");
//    }

    if ( mTexShader.a_Position == -1 || mTexShader.a_Normal == -1 || mTexShader.a_TexCoord == -1 ||
    	   mTexShader.u_MvpMatrix == -1 || mTexShader.u_NormalMatrix == -1) {
    	     throw new RuntimeException("attribute、uniform変数の格納場所の取得に失敗");
      }

    mCube = initVertexBuffers();    // 頂点情報を設定する

    //mGraph = initVertexBuffers2();    // グラフを表示設定する

    mTexture = initTextures(mTexShader);  // テクスチャを設定する

    // クリアカラーを設定し、デプステストを有効にする
    GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    GLES20.glEnable(GLES20.GL_BLEND);

//    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
//    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    GLES20.glClearColor(1.0f, 1.0f, 2.0f, 1.0f);


    mLast = SystemClock.uptimeMillis();
  }

  public void onSurfaceChanged(GL10 gl, int width, int height) {
    GLES20.glViewport(0, 0, width, height);     // 表示領域を設定する

    mSize = (width < height) ? (float)width : (float)height;

    // ビュー投影行列を計算する
    float[] projMatrix = new float[16];
    float[] viewMatrix = new float[16];

    Utils.setPerspectiveM(projMatrix, 0, 30.0, (double)width / height, 1.0, 100.0);
//    Matrix.setLookAtM(viewMatrix, 0, 0.0f, 0.0f, 20.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
    Matrix.setLookAtM(viewMatrix, 0, 0.0f, 0.0f, 60.0f, 10.0f, 0.0f, 0.0f, 0.0f, 1.0f,0.0f);
    Matrix.multiplyMM(mViewProjMatrix, 0, projMatrix, 0, viewMatrix, 0);

    mLast = SystemClock.uptimeMillis();
  }

  public void onDrawFrame(GL10 gl) {
//    mCurrentAngle = animate(mCurrentAngle);  // 回転角度を更新する

    // カラーバッファとデプスバッファをクリア
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

    // 単色で立方体を描画する
//    drawSolidCube(mSolidShader, mGraph, -1.8f, mCurrentAngle);

//    drawSolidCube(mTexShader, mGraph, -1.8f, mCurrentAngle);

    // テクスチャ付きで立方体を描画する
    drawTexCube(mTexShader, mCube, mTexture, 1.8f, mCurrentAngle);
  }




  private Model initVertexBuffers() {

	  Data3DList data3D_list = new Data3DList(this.getApplicationContext());
      data3D_list.readData("3D_images/V0002.dat");
      System.out.println(data3D_list.getDatSize());
      System.out.println(data3D_list.getNGListCount());

      Data3D data = null;
      for(int i=0;i<data3D_list.getNGListCount();i++){

      	data = data3D_list.getData3D(i);
      	System.out.println(data.get3DputData().length);

      }

      FloatBuffer vertices = Utils.makeFloatBuffer(data.get3DputData());


//テスト
//      FloatBuffer vertices = Utils.makeFloatBuffer(new float[] {     // 頂点座標
//    		  0,0,-5,	1,2,-5,		2,2,-5,		3,0,-5,
//    		  0,2,-4,	1,2,-4,		2,2,-4,		3,0,-4,
//    		  0,0,-3,	1,0,-3,		2,0,-3,		3,0,-3,
//      });
//
//      ByteBuffer indices2 = Utils.makeByteBuffer(new byte[] {     // 頂点座標
//    		  0,1,5, 0,4,5,
//    		  1,2,6, 1,5,6,
//    		  2,3,7, 2,6,7,
//
//    		  4,5,9, 4,8,9,
//    		  5,6,10,5,9,10,
//    		  6,7,11,6,10,11,
//      });

      int gridU = 33; //W 幅
      int gridV = 33; //H 高

      //インデックス配列
      //byte[] indices3 = new byte[((gridV-1) * gridU * 2) * 3];
      float[] indices3 = new float[((gridV-1) * gridU * 2) * 3];

      int cnt=0;
      //Indexs値の[1番目]
      float oneInt = 0;
      //Indexs値の[3番目]
      float threeInt =34;

      //Indexs値の[2番目]
      //偶数配列の番地[2,4,8,10...]
      float two2Int =33;

      //Indexs値の[2番目]
      //奇数配列の番地[0,1,3,5,7...]
      float one2Int =1;

      for (int iu=1; iu <= gridU * gridV*6; ++iu){
			if(cnt == 6336){
				String aaaaa = "ss";
				break;
			}
    	  //偶数
    	  if(iu%2==0 ){

    		  indices3[cnt++] = (float) oneInt;	//[1番目]: 0
//    		  Log.d("INDEX値", "indexs["+(cnt-1)+"]:"+indices3[cnt-1]);

			  indices3[cnt++] = (float) two2Int;	//[2番目]: 33
//			  Log.d("INDEX値", "indexs["+(cnt-1)+"]:"+indices3[cnt-1]);

			  indices3[cnt++] = (float)threeInt;	//[3番目]: 34
//			  Log.d("INDEX値", "indexs["+(cnt-1)+"]:"+indices3[cnt-1]);

			  oneInt++;		//[1番目]の数値を＋１
			  two2Int++;	//[2番目]の数値を＋１
			  threeInt++;	//[3番目]の数値を＋１
    	  }else{

    		  //奇数
    		  if(iu==1){

    			  indices3[cnt++] = (float) oneInt;   //[1番目]: 0
//    			  Log.d("INDEX値", "indexs["+(cnt-1)+"]:"+indices3[cnt-1]);

    			  indices3[cnt++] = (float) one2Int;  //[2番目]: 1
//    			  Log.d("INDEX値", "indexs["+(cnt-1)+"]:"+indices3[cnt-1]);

    			  indices3[cnt++] = (float) threeInt; //[3番目]: 34
//    			  Log.d("INDEX値", "indexs["+(cnt-1)+"]:"+indices3[cnt-1]);

    			  one2Int++;
    		  }else{
        		  indices3[cnt++] = (float) oneInt;	 //[1番目]: 1
//        		  Log.d("INDEX値", "indexs["+(cnt-1)+"]:"+indices3[cnt-1]);

    			  indices3[cnt++] = (float) one2Int;//[2番目]: 2
//    			  Log.d("INDEX値", "indexs["+(cnt-1)+"]:"+indices3[cnt-1]);

    			  indices3[cnt++] = (float) threeInt; //[3番目]: 35
//    			  Log.d("INDEX値", "indexs["+(cnt-1)+"]:"+indices3[cnt-1]);

    			  one2Int++;
    		  }
    	  }
      }

      FloatBuffer indices2 = Utils.makeFloatBuffer(indices3);

//      FloatBuffer indices2 = Utils.makeFloatBuffer(new float[] {     // 頂点座標
//    		  245,246,279,  245,278,279,
//
//
//
//      });

    // 頂点情報をバッファオブジェクトに書き込む
    Model model = new Model(); // バッファオブジェクトの管理にModelクラスを利用する
    model.vertexBuffer = initArrayBufferForLaterUse(vertices, 3, GLES20.GL_FLOAT);
    model.normalBuffer = initArrayBufferForLaterUse(vertices, 3, GLES20.GL_FLOAT);
//    model.texCoordBuffer = initArrayBufferForLaterUse(texCoords, 2, GLES20.GL_FLOAT);

//    model.colorBuffer = initArrayBufferForLaterUse(vertices, 3, GLES20.GL_FLOAT);

//    model.texCoordBuffer = initArrayBufferForLaterUse(vertices, 2, GLES20.GL_FLOAT);
//    model.indexBuffer = initElementArrayBufferForLaterUse(indices2, GLES20.GL_UNSIGNED_BYTE);
    model.indexBuffer = initElementArrayFloatForLaterUse(indices2, GLES20.GL_FLOAT);
    model.numIndices = indices2.limit();

    return model;
  }


//
//  /**
//   * x,y,zで作るグラフ
//   * @return
//   */
//  private Model initVertexBuffers2() {
//
////    FloatBuffer vertices = Utils.makeFloatBuffer(new float[] {     // 頂点座標
////
////    		// x1,  y1,  z1,
////    		 1.0f, 1.0f, 1.0f,
////    		 1.0f, -1.0f, 1.0f,
////
////	    });
////
////    ByteBuffer indices = Utils.makeByteBuffer(new byte[] {     // インデックス
////
////    		   0, 1,
////
////    });
//
//	    FloatBuffer vertices = Utils.makeFloatBuffer(new float[] {     // 頂点座標
//	 	       1.0f, 1.0f, 1.0f,  -1.0f, 1.0f, 1.0f,  -1.0f,-1.0f, 1.0f,   1.0f,-1.0f, 1.0f,    // v0-v1-v2-v3 前
//	 	       1.0f, 1.0f, 1.0f,   1.0f,-1.0f, 1.0f,   1.0f,-1.0f,-4.0f,   1.0f, 1.0f,-4.0f,    // v0-v3-v4-v5 右
//	 	       1.0f, 1.0f, 1.0f,   1.0f, 1.0f,-4.0f,  -1.0f, 1.0f,-4.0f,  -1.0f, 1.0f, 1.0f,    // v0-v5-v6-v1 上
//	 	      -1.0f, 1.0f, 1.0f,  -1.0f, 1.0f,-4.0f,  -1.0f,-1.0f,-4.0f,  -1.0f,-1.0f, 1.0f,    // v1-v6-v7-v2 左
//	 	      -1.0f,-1.0f,-4.0f,   1.0f,-1.0f,-4.0f,   1.0f,-1.0f, 1.0f,  -1.0f,-1.0f, 1.0f,    // v7-v4-v3-v2 下
//	 	       1.0f,-1.0f,-4.0f,  -1.0f,-1.0f,-4.0f,  -1.0f, 1.0f,-4.0f,   1.0f, 1.0f,-4.0f     // v4-v7-v6-v5 奥
//	 	    });
//
//	     ByteBuffer indices = Utils.makeByteBuffer(new byte[] {     // インデックス
//	        0, 1, 2,3,   1, 2, 3,    // 前
//	        4, 5, 6,7,   4, 6, 7,    // 右
//	        8, 9,10,11,  9,10,11,    // 上
//	       12,13,14,15,  12,14,15,    // 左
//	       16,17,18,19,  17,18,20,    // 下
//	       20,21,22,23,  20,22,23     // 奥
//	     });
//
//
//    // 頂点情報をバッファオブジェクトに書き込む
//    Model model = new Model(); // バッファオブジェクトの管理にModelクラスを利用する
//    model.vertexBuffer = initArrayBufferForLaterUse(vertices, 3, GLES20.GL_FLOAT);
//    model.normalBuffer = initArrayBufferForLaterUse(vertices, 3, GLES20.GL_FLOAT);
//    model.texCoordBuffer = initArrayBufferForLaterUse(vertices, 2, GLES20.GL_FLOAT);
//    model.indexBuffer = initElementArrayBufferForLaterUse(indices, GLES20.GL_UNSIGNED_BYTE);
//    model.numIndices = indices.limit();
//
//    return model;
//  }


  private int initTextures(Shader shader) {
    int[] texture = new int[1];
    GLES20.glGenTextures(1, texture, 0);   // テクスチャオブジェクトを作成する

    Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.orange);  // 画像オブジェクトを作成する
//    Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.v0002);  // 画像オブジェクトを作成する
    if (image == null) {
      throw new RuntimeException("画像オブジェクトの作成に失敗");
    }

    // テクスチャオブジェクトに画像データを書きこむ
    GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);

    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, image, 0);

    // サンプラにテクスチャユニット0を設定する
    GLES20.glUseProgram(shader.program);
    GLES20.glUniform1i(shader.u_Sampler, 0);

    return texture[0];
  }

  private void drawSolidCube(Shader shader, Model cube, float x, float[] angle) {
    GLES20.glUseProgram(shader.program);   // このプログラムオブジェクトを使用することを伝える

    // バッファオブジェクトをattribute変数に割り当て、有効にする
    initAttributeVariable(shader.a_Position, cube.vertexBuffer); // 頂点座標
    initAttributeVariable(shader.a_Normal, cube.normalBuffer);   // 法線
    GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, cube.indexBuffer.buffer);  // インデックスをバインドする




    drawCube(shader, cube, x, angle, mViewProjMatrix);   // 描画する
  }

  /**
   * cubeを作成する
   * @param shader
   * @param cube
   * @param texture
   * @param x
   * @param angle
   */
  private void drawTexCube(Shader shader, Model cube, int texture, float x, float[] angle) {
    GLES20.glUseProgram(shader.program);   // このプログラムオブジェクトを使用することを伝える

    // バッファオブジェクトをattribute変数に割り当て、有効にする
    initAttributeVariable(shader.a_Position, cube.vertexBuffer);  // 頂点座標
    initAttributeVariable(shader.a_Normal, cube.normalBuffer);    // 法線
//    initAttributeVariable(shader.a_Color, cube.colorBuffer);    // カラー

//    initAttributeVariable(shader.a_TexCoord, cube.texCoordBuffer);// テクスチャ座標
    GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, cube.indexBuffer.buffer);  // インデックスをバインドする

    // テクスチャユニット0にテクスチャオブジェクトをバインドする
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);

    drawCube(shader, cube, x, angle, mViewProjMatrix); // 描画する
  }

  // バッファオブジェクトをattribute変数に割り当て、有効にする
  private void initAttributeVariable(int a_attribute, BufferObject buffer) {
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffer.buffer);
    GLES20.glVertexAttribPointer(a_attribute, buffer.num, buffer.type, false, 0, 0);
    GLES20.glEnableVertexAttribArray(a_attribute);
  }

  private void drawCube(Shader shader, Model cube, float x, float[] angle, float[] viewProjMatrix) {
    // モデル変換行列を計算する
    Matrix.setIdentityM(mModelMatrix, 0);
    Matrix.translateM(mModelMatrix, 0, x, 0.0f, 0.0f);
    Matrix.rotateM(mModelMatrix, 0, 20.0f, 1.0f, 0.0f, 0.0f);
//    Matrix.rotateM(mModelMatrix, 0, angle, 0.0f, 1.0f, 0.0f);

    Matrix.rotateM(mModelMatrix, 0, angle[0], 1.0f, 0.0f, 0.0f); // x軸の回転
	Matrix.rotateM(mModelMatrix, 0, angle[1], 0.0f, 1.0f, 0.0f); // y軸の回転

    Matrix.scaleM(mModelMatrix, 0, mScale, mScale, mScale);    // 拡大・縮小する


    // 法線の変換行列を計算し、u_NormalMatrix変数に設定する
    float[] inv = new float[16];
    Matrix.invertM(inv, 0, mModelMatrix, 0);
    Matrix.transposeM(mNormalMatrix, 0, inv, 0);
    GLES20.glUniformMatrix4fv(shader.u_NormalMatrix, 1, false, mNormalMatrix, 0);

    // モデルビュー投影行列を計算し、u_MvpMatrix変数に設定する
    Matrix.multiplyMM(mMvpMatrix, 0, viewProjMatrix, 0, mModelMatrix, 0);
    GLES20.glUniformMatrix4fv(shader.u_MvpMatrix, 1, false, mMvpMatrix, 0);

    GLES20.glDrawElements(GLES20.GL_TRIANGLES, cube.numIndices, GLES20.GL_UNSIGNED_BYTE, 0);   // 描画する

//    GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, cube.numIndices, GLES20.GL_UNSIGNED_BYTE, 0);   // 描画する


  }

  private BufferObject initArrayBufferForLaterUse(FloatBuffer data, int num, int type) {
    final int FSIZE = Float.SIZE / Byte.SIZE; // floatのバイト数
    int[] buffer = new int[1];
    GLES20.glGenBuffers(1, buffer, 0);   // バッファオブジェクトを作成する
    // バッファオブジェクトにデータを書き込む
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffer[0]);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, FSIZE * data.limit(), data, GLES20.GL_STATIC_DRAW);

    // 後でattribute変数に割り当てるのに必要な情報を設定しておく
    BufferObject bufferObject = new BufferObject();
    bufferObject.buffer = buffer[0];
    bufferObject.num = num;
    bufferObject.type = type;

    return bufferObject;
  }


  private BufferObject initElementArrayFloatForLaterUse(FloatBuffer data, int type) {
	    final int FSIZE = Float.SIZE / Byte.SIZE; // floatのバイト数
	    int[] buffer = new int[1];
	    GLES20.glGenBuffers(1, buffer, 0);   // バッファオブジェクトを作成する
	    // バッファオブジェクトにデータを書き込む
	    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffer[0]);
	    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, data.limit(), data, GLES20.GL_STATIC_DRAW);

	    // 後でattribute変数に割り当てるのに必要な情報を設定しておく
	    BufferObject bufferObject = new BufferObject();
	    bufferObject.buffer = buffer[0];
	    bufferObject.type = type;

	    return bufferObject;
	  }

  private BufferObject initElementArrayShortBufferForLaterUse(ShortBuffer data, int type) {
	    int[] buffer = new int[1];
	    GLES20.glGenBuffers(1, buffer, 0);    // バッファオブジェクトを作成する
	    // バッファオブジェクトにデータを書き込む
	    GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, buffer[0]);
	    GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, data.limit(), data, GLES20.GL_STATIC_DRAW);

	    BufferObject bufferObject = new BufferObject();
	    bufferObject.buffer = buffer[0];
	    bufferObject.type = type;

	    return bufferObject;
	  }


  private BufferObject initElementArrayBufferForLaterUse(ByteBuffer data, int type) {
    int[] buffer = new int[1];
    GLES20.glGenBuffers(1, buffer, 0);    // バッファオブジェクトを作成する
    // バッファオブジェクトにデータを書き込む
    GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, buffer[0]);
    GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, data.limit(), data, GLES20.GL_STATIC_DRAW);

    BufferObject bufferObject = new BufferObject();
    bufferObject.buffer = buffer[0];
    bufferObject.type = type;

    return bufferObject;
  }

  private static final float ANGLE_STEP = 120.0f;   // 回転角の増分(度)
  private float animate(float angle) {
    long now = SystemClock.uptimeMillis();   // 前回呼び出されてからの経過時間を計算
    long elapsed = now - mLast;
    mLast = now;
    // 回転角度を更新する（経過時間により調整）
    float newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0f;
    return newAngle %= 360;
  }
}